﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

public static class ServiceManage
{
    private static Dictionary<string, IServiceCollection> servicePairs;

    private static ConcurrentDictionary<string, IServiceProvider> providerPairs;

    private static object ProviderLock { get; set; }

    static ServiceManage()
    {
        servicePairs = new Dictionary<string, IServiceCollection>();
        providerPairs = new ConcurrentDictionary<string, IServiceProvider>();
        ProviderLock = new object();
        lock (ProviderLock)
        {
            if (!servicePairs.ContainsKey("default"))
            {
                ServiceCollection value = new ServiceCollection();
                servicePairs.Add("default", value);
            }
        }
    }

    public static T Get<T>(string providerName = "default") where T : class
    {
        try
        {
            if (providerPairs.TryGetValue(providerName, out IServiceProvider value))
            {
                return value.GetService<T>();
            }

            if (servicePairs.TryGetValue(providerName, out IServiceCollection value2))
            {
                lock (ProviderLock)
                {
                    if (!providerPairs.TryGetValue(providerName, out value))
                    {
                        value = value2.BuildServiceProvider();
                        providerPairs.TryAdd(providerName, value);
                    }
                }
            }

            return (value != null) ? value.GetService<T>() : null;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public static object Get(Type type, string providerName = "default")
    {
        try
        {
            if (providerPairs.TryGetValue(providerName, out IServiceProvider value))
            {
                return value.GetService(type);
            }

            if (servicePairs.TryGetValue(providerName, out IServiceCollection value2))
            {
                lock (ProviderLock)
                {
                    if (!providerPairs.TryGetValue(providerName, out value))
                    {
                        value = value2.BuildServiceProvider();
                        providerPairs.TryAdd(providerName, value);
                    }
                }
            }

            return value?.GetService(type);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public static IServiceCollection GetServiceCollection(string providerName = "default", IServiceCollection services = null)
    {
        lock (ProviderLock)
        {
            if (services != null)
            {
                providerPairs.TryRemove(providerName, out IServiceProvider _);
                if (servicePairs.ContainsKey(providerName))
                {
                    servicePairs[providerName] = services;
                }
                else
                {
                    servicePairs.Add(providerName, services ?? new ServiceCollection());
                }
            }
            else if (!servicePairs.ContainsKey(providerName))
            {
                servicePairs.Add(providerName, services ?? new ServiceCollection());
            }

            return servicePairs[providerName];
        }
    }

    public static string RegisterServiceProvider(IServiceProvider serviceProvider, string providerName = "default")
    {
        IServiceProvider serviceProvider2 = serviceProvider;
        lock (ProviderLock)
        {
            providerPairs.AddOrUpdate(providerName, serviceProvider2, (string a, IServiceProvider b) => serviceProvider2);
        }

        return string.Empty;
    }
    public static IServiceProvider? GetServiceProvider(string providerName = "default")
    {
        try
        {
            if (providerPairs.TryGetValue(providerName, out IServiceProvider value))
            {
                return value;
            }

            if (servicePairs.TryGetValue(providerName, out IServiceCollection value2))
            {
                lock (ProviderLock)
                {
                    if (!providerPairs.TryGetValue(providerName, out value))
                    {
                        value = value2.BuildServiceProvider();
                        providerPairs.TryAdd(providerName, value);
                    }
                }
            }

            return (value != null) ? value : null;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public static void Clear(string providerName = "default")
    {
        lock (ProviderLock)
        {
            if (servicePairs.ContainsKey(providerName))
            {
                ServiceCollection value = new ServiceCollection();
                servicePairs[providerName] = value;
                providerPairs.TryRemove(providerName, out IServiceProvider _);
            }
        }
    }
}
